package com.weihe.toolkit.cypt;
import java.io.IOException;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.codec.binary.Base64;

/** 
 * 常用加密算法工具类 
 * @author cq 
 */  
public class EncryptUtils {  
      
    /** 
     * 用MD5算法进行加密 
     * @param str 需要加密的字符串 
     * @return MD5加密后的结果 
     */  
    public static String encodeMD5String(String str) {  
        return encode(str, "MD5");  
    }  

    /** 
     * 用SHA算法进行加密 
     * @param str 需要加密的字符串 
     * @return SHA加密后的结果 
     */  
    public static String encodeSHAString(String str) {  
        return encode(str, "SHA");  
    }  

    /** 
     * 用base64算法进行加密 
     * @param str 需要加密的字符串 
     * @return base64加密后的结果 
     */  
    public static String encodeBase64String(String str) {
    	return new String(Base64.encodeBase64(str.getBytes()));
//        BASE64Encoder encoder =  new BASE64Encoder();  
//        return encoder.encode(str.getBytes());  
    }  
      
    /** 
     * 用base64算法进行解密 
     * @param str 需要解密的字符串 
     * @return base64解密后的结果 
     * @throws IOException  
     */  
    public static String decodeBase64String(String str) throws IOException {
    	return new String(Base64.decodeBase64(str.getBytes()));
//        BASE64Decoder encoder =  new BASE64Decoder();  
//        return new String(encoder.decodeBuffer(str));  
    }  
      
    private static String encode(String str, String method) {  
        MessageDigest md = null;  
        String dstr = null;  
        try {  
            md = MessageDigest.getInstance(method);  
            md.update(str.getBytes());  
            dstr = new BigInteger(1, md.digest()).toString(16);  
        } catch (NoSuchAlgorithmException e) {  
            e.printStackTrace();  
        }  
        return dstr;  
    }
    
    
    
    
    
    
    private final static String DES = "DES";

	/**
	 * 加密
	 * 
	 * @param src
	 *            数据源
	 * @param key
	 *            密钥，长度必须是8的倍数
	 * @return 返回加密后的数据
	 * @throws Exception
	 */
	public static byte[] desEncrypt(byte[] src, byte[] key)
			throws RuntimeException {
		// DES算法要求有一个可信任的随机数源
		try {
			SecureRandom sr = new SecureRandom();
			// 从原始密匙数据创建DESKeySpec对象
			DESKeySpec dks = new DESKeySpec(key);
			// 创建一个密匙工厂，然后用它把DESKeySpec转换成
			// 一个SecretKey对象
			SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(DES);
			SecretKey securekey = keyFactory.generateSecret(dks);
			// Cipher对象实际完成加密操作
			Cipher cipher = Cipher.getInstance(DES);
			// 用密匙初始化Cipher对象
			cipher.init(Cipher.ENCRYPT_MODE, securekey, sr);
			// 现在，获取数据并加密
			// 正式执行加密操作
			return cipher.doFinal(src);
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	/**
	 * 解密
	 * 
	 * @param src
	 *            数据源
	 * @param key
	 *            密钥，长度必须是8的倍数
	 * @return 返回解密后的原始数据
	 * @throws Exception
	 */
	public static byte[] desDecrypt(byte[] src, byte[] key)
			throws RuntimeException {
		try {
			// DES算法要求有一个可信任的随机数源
			SecureRandom sr = new SecureRandom();
			// 从原始密匙数据创建一个DESKeySpec对象
			DESKeySpec dks = new DESKeySpec(key);
			// 创建一个密匙工厂，然后用它把DESKeySpec对象转换成
			// 一个SecretKey对象
			SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(DES);
			SecretKey securekey = keyFactory.generateSecret(dks);
			// Cipher对象实际完成解密操作
			Cipher cipher = Cipher.getInstance(DES);
			// 用密匙初始化Cipher对象
			cipher.init(Cipher.DECRYPT_MODE, securekey, sr);
			// 现在，获取数据并解密
			// 正式执行解密操作
			return cipher.doFinal(src);
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	/**
	 * 数据解密
	 * 
	 * @param data
	 * @param key
	 *            密钥
	 * @return
	 * @throws Exception
	 */
	public final static String desDecrypt(String data, String key)
			throws Exception {
		return new String(desDecrypt(hex2byte(data.getBytes()), key.getBytes()));
	}

	/**
	 * 数据加密
	 * 
	 * @param data
	 * @param key
	 *            密钥
	 * @return
	 * @throws Exception
	 */
	public final static String desEncrypt(String data, String key) {
		if (data != null)
			try {
				return byte2hex(desEncrypt(data.getBytes(), key.getBytes()));
			} catch (Exception e) {
				throw new RuntimeException(e);
			}
		return null;
	}

	/**
	 * 二行制转字符串
	 * 
	 * @param b
	 * @return
	 */
	private static String byte2hex(byte[] b) {
		StringBuilder hs = new StringBuilder();
		String stmp;
		for (int n = 0; b != null && n < b.length; n++) {
			stmp = Integer.toHexString(b[n] & 0XFF);
			if (stmp.length() == 1)
				hs.append('0');
			hs.append(stmp);
		}
		return hs.toString().toUpperCase();
	}

	private static byte[] hex2byte(byte[] b) {
		if ((b.length % 2) != 0)
			throw new IllegalArgumentException();
		byte[] b2 = new byte[b.length / 2];
		for (int n = 0; n < b.length; n += 2) {
			String item = new String(b, n, 2);
			b2[n / 2] = (byte) Integer.parseInt(item, 16);
		}
		return b2;
	}
	
	
	
	
	
	/**
     * AES加密
     */ 
    public static String aesEncrypt(String seed, String cleartext) 
            throws Exception { 
        byte[] rawKey = getRawKey(seed.getBytes()); 
        byte[] result = aesEncrypt(rawKey, cleartext.getBytes()); 
        return toHex(result); 
    } 
 
    /**
     * AES解密
     */ 
    public static String aesDecrypt(String seed, String encrypted) 
            throws Exception { 
        if (seed == null || "".equals(seed) || encrypted == null || "".equals(encrypted)){ 
            return null; 
        } 
        byte[] rawKey = getRawKey(seed.getBytes()); 
        byte[] enc = toByte(encrypted); 
        byte[] result = aesDecrypt(rawKey, enc); 
        return new String(result); 
    } 
 
    private static byte[] getRawKey(byte[] seed) throws Exception { 
        KeyGenerator kgen = KeyGenerator.getInstance("AES"); 
        SecureRandom sr = SecureRandom.getInstance("SHA1PRNG"); 
        sr.setSeed(seed); 
        kgen.init(128, sr); // 192 and 256 bits may not be available 
        SecretKey skey = kgen.generateKey(); 
        byte[] raw = skey.getEncoded(); 
        return raw; 
    } 
 
    private static byte[] aesEncrypt(byte[] raw, byte[] clear) throws Exception { 
        if (raw == null || clear == null){ 
            return null; 
        } 
        SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES"); 
        Cipher cipher = Cipher.getInstance("AES"); 
        cipher.init(Cipher.ENCRYPT_MODE, skeySpec); 
        byte[] encrypted = cipher.doFinal(clear); 
        return encrypted; 
    } 
 
    private static byte[] aesDecrypt(byte[] raw, byte[] encrypted) 
            throws Exception { 
        SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES"); 
        Cipher cipher = Cipher.getInstance("AES"); 
        cipher.init(Cipher.DECRYPT_MODE, skeySpec); 
        byte[] decrypted = cipher.doFinal(encrypted); 
        return decrypted; 
    } 
 
    public static String toHex(String txt) { 
        return toHex(txt.getBytes()); 
    } 
 
    public static String fromHex(String hex) { 
        return new String(toByte(hex)); 
    } 
 
    public static byte[] toByte(String hexString) { 
        if (hexString == null || "".equals(hexString)){ 
            return null; 
        } 
        int len = hexString.length() / 2; 
        byte[] result = new byte[len]; 
        for (int i = 0; i < len; i++) { 
            result[i] = Integer.valueOf(hexString.substring(2 * i, 2 * i + 2), 16).byteValue(); 
        } 
        return result; 
    } 
 
    public static String toHex(byte[] buf) { 
        if (buf == null) 
            return ""; 
        StringBuffer result = new StringBuffer(2 * buf.length); 
        for (int i = 0; i < buf.length; i++) { 
            appendHex(result, buf[i]); 
        } 
        return result.toString(); 
    } 
 
    private final static String HEX = "0123456789ABCDEF"; 
 
    private static void appendHex(StringBuffer sb, byte b) { 
        sb.append(HEX.charAt((b >> 4) & 0x0f)).append(HEX.charAt(b & 0x0f)); 
    } 
      
    public static void main(String[] args) throws Exception {  
//        String user = "oneadmin";  
//        System.out.println("原始字符串 " + user);  
//        System.out.println("MD5加密 " + encodeMD5String(user));  
//        System.out.println("SHA加密 " + encodeSHAString(user));  
//        String base64Str = encodeBase64String(user);  
//        System.out.println("Base64加密 " + base64Str);  
//        System.out.println("Base64解密 " + decodeBase64String(base64Str));  
//    	String text = "abcde";
//    	String password = "aaabbb";
//    	String a = EncryptUtils.desEncrypt(text, password);
//    	System.out.println(a);
//    	System.out.println(EncryptUtils.desDecrypt(a, password));
    	
//    	String a = EncryptUtils.aesEncrypt(password, text);
//    	System.out.println(a);
//    	System.out.println(EncryptUtils.aesDecrypt(password, a));
    	
    	String s = "http://www.javaidea.net/list.jsp?topic=5";
    	System.out.println(EncryptUtils.encodeBase64String(s));
    	System.out.println(EncryptUtils.decodeBase64String(EncryptUtils.encodeBase64String(s)));
    }  
}  